import { ref, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import { useCurrentInstance } from '@/common/hooks';
import { sleep } from '@/common/utils';
import { PayType } from '@/env';
import { postZlCardConfirmPayment } from '@/common/request/api'
import type { PurchaseGoodsPayData, BankCardItem, JinQianBaPayData } from '@/common/request/api';
import { stripePay, yaBandPay, sandPay, mpAppPay, alimappPay, appPay } from '../utils/pay';
import type { MpPaymentParams } from '@/common/wxinit';
import { onShow } from '@dcloudio/uni-app';

export interface PayParamMap {
	[PayType.SYS] : any;
	[PayType.CASH] : any;
	[PayType.OFFLINE] : any;
	[PayType.STRIPE] : string;
	[PayType.YABAND] : any;
	[PayType.HM] : any;
	[PayType.SAND] : any;
	[PayType.UIPAY] : any;
	[PayType.CYBERSOURCE] : string;
	[PayType.WX] : MpPaymentParams;
	[PayType.ZFB] : any;
	[PayType.JINQIANBA] : string;
}

export interface miniappPayParamMap {
	[PayType.HM] : MpPaymentParams;
	[PayType.SAND] : MpPaymentParams;
	[PayType.UIPAY] : { payData : string };
	[PayType.CYBERSOURCE] : string;
	[PayType.WX] : string;
	[PayType.ZFB] : string;
	[PayType.JINQIANBA] : string;
}

type CbRequestApi = (...args : any[]) => Promise<PurchaseGoodsPayData>;

export const reRequest = async <A extends CbRequestApi>(api : A, num = 0, ...args : any[]) => {
	let res = await api.apply(this, args);
	await sleep(1000);
	for (let i = num; i < 4; i++) {
		if (res.code === 302 && i < 4) {
			res = await api.apply(this, args);
			await sleep(1000);
		} else {
			break;
		}
	}
	return res;
};

const supperAppPay = (payType : PayType, payParams : PurchaseGoodsPayData<PayParamMap[PayType]>) =>
	new Promise<void>((resolve, reject) => {
		const subPayType = uni.getStorageSync('subPayType');

		uni.sendNativeEvent(
			'appPay',
			{
				payType,
				payParams,
				subPayType
			},
			(ret) => {
				if (ret) {
					resolve();
				} else {
					reject();
				}
			}
		);
	});

export const usePay = () => {
	const ctx = useCurrentInstance();
	const { t } = useI18n();
	const payLoading = ref(false);
	let hasShowPayModal = false; // 是否调用了YaBandPay 是则在onshow时弹窗询问用户是否支付成功
	// 用户确认YaBandPay支付成功时，调用的回调函数
	let showPayModalCB : Function | null;
	const cardValidCodePopupShow = ref(false)
	let cardId : number
	const checkCardPay = (payType : PayType, cb : (cid : number) => void) => {
		const subPayType = uni.getStorageSync('subPayType');

		if (payType === PayType.ZL && subPayType === '5') {

			ctx.$goTo(
				'/pages/user/bankCard/index',
				{ type: 1 },
				{
					SelectBankCard: (data : BankCardItem) => {
						uni.showLoading({
							title: 'loading...',
							mask: true
						});
						payLoading.value = true
						cardId = data.id
						cb(data.id)
					}
				}
			);
			return true
		}
		return false
	}
	let cardPayParams = ''
	let awaitCardPayCb : Function
	let awaitCardPayErrCb : Function
	const handleCardPay = (code : string) => {
		cardValidCodePopupShow.value = false
		if (code) {
			let data = JSON.parse(cardPayParams)
			data['bankId'] = cardId
			postZlCardConfirmPayment({
				code,
				data: JSON.stringify(data)
			}).then(() => {
				awaitCardPayCb?.()
			})
		}

	}
	const handleCancelCardPay = () => {
		cardValidCodePopupShow.value = false
		awaitCardPayErrCb?.()
	}
	const awaitCardPay = () => new Promise<void>((resolve, reject) => {
		awaitCardPayCb = resolve
		awaitCardPayErrCb = reject
	})
	const systemPay = async <A extends CbRequestApi>({
		payType,
		resolveData,
		api,
		storageKey,
		orderIdKey = 'paycode',
		offlinePayCode = 'paycode',
		successUrl,
		errorUrl,
		orderUrl,
		payUrl,
		payParams,
		callBack,
		isTrace,
		requireOrder,
		payMoney
	} : {
		payType : PayType; //支付类型
		resolveData : PurchaseGoodsPayData<PayParamMap[PayType]>; //下单接口返回的数据
		api ?: A; //查询订单是否支付成功的接口
		storageKey : string; //h5支付缓存的订单id字段
		payUrl ?: string; //h5支付跳转的页面
		payParams ?: miniappPayParamMap[keyof miniappPayParamMap]; //额外的支付参数，例如小程序调用系统api支付或CYBERSOURCE创建表单进行支付
		successUrl ?: (s : PurchaseGoodsPayData[keyof PurchaseGoodsPayData]) => string; //支付成功跳转的页面地址
		errorUrl ?: (s : string) => string; //支付失败跳转的页面地址
		orderIdKey ?: keyof PurchaseGoodsPayData; //其它支付方式返回的订单id字段
		offlinePayCode ?: keyof PurchaseGoodsPayData; //线下支付返回的订单id字段
		callBack ?: Function; //自定义回调
		orderUrl ?: string; //订单列表地址
		isTrace ?: boolean; //是否为视频带货订单
		requireOrder ?: boolean; //视频带货订单是否需要推单
		payMoney ?: number | string
	}) => {
		// 状态码非200即支付失败，直接跳转失败页面
		if (resolveData.code !== 200) {
			errorUrl && ctx.$goTo(`/pages/${errorUrl(resolveData.msg)}`);
			return;
		}
		if (payType === PayType.DFK) {
			ctx.$goTo(`/pages/${successUrl(resolveData.msg)}`);
			return
		}
		const subPayType = uni.getStorageSync('subPayType');



		const getPayStatus = () => {
			if (api) {
				payLoading.value = true;
				reRequest(api, 0, resolveData[orderIdKey])
					.then((resultRes) => {
						payLoading.value = false;
						if (callBack) {
							callBack(resultRes);
						} else {
							successUrl && ctx.$goRedirectTo(`/pages/${successUrl(resultRes[orderIdKey])}`);
						}
					})
					.catch((res) => {
						errorUrl && ctx.$goTo(`/pages/${errorUrl(res.msg)}`);
					});
			}
		};

		if (payType === PayType.ZL && subPayType === '5') {
			cardPayParams = resolveData.data as string
			cardValidCodePopupShow.value = true
			await awaitCardPay()
			uni.hideLoading();
			getPayStatus();
			return
		}
		if ([PayType.SYS, PayType.CASH].includes(payType)) {
			if (callBack) {
				callBack();
			} else {
				// 系统支付与货到付款，无需额外操作
				successUrl && ctx.$goRedirectTo(`/pages/${successUrl(resolveData[orderIdKey])}`);
			}

		} else {
			if (resolveData.state && resolveData.state === '1') {
				uni.hideLoading();
				// 0元订单，不用支付，直接走回调
				if (callBack) {
					callBack({ noPay: true });
				} else {
					successUrl &&
						uni.redirectTo({
							url: `/pages/${successUrl(resolveData[orderIdKey])}`
						});
				}
				return;
			}
			const payPromise = async <A extends (...args : any[]) => Promise<any>>(payApi : A, ...args : Parameters<A>) => {
				try {
					await payApi.apply(ctx, args);
					if (api) {
						await sleep(1500);
						getPayStatus();

					} else {
						if (callBack) {
							callBack();
						} else {
							successUrl && ctx.$goRedirectTo(`/pages/${successUrl(resolveData[orderIdKey])}`);
						}
					}
				} catch (e) {
					if (callBack) {
						callBack();
					} else {
						orderUrl && ctx.$goRedirectTo(`/pages/${orderUrl}`);
					}
				}
			};
			uni.showLoading({
				title: 'loading...',
				mask: process.env.NODE_ENV === 'development' ? false : true
			});
			if (payType === PayType.OFFLINE) {
				// 线下支付
				uni.hideLoading();
				ctx.$goRedirectTo(`/pages/offlinePay?code=${resolveData[offlinePayCode]}`);
			} else if (payType === PayType.JINQIANBA) {

				const __Data : JinQianBaPayData = JSON.parse(payParams as string);
				// #ifdef H5
				// #ifdef SUBSCRIPTION || PRIVATE
				if (__Data.payType === 'WX_JSAPI') {
					// 用进钱吧的支付参数入微信支付的参拉起公众号微信支付
					uni.hideLoading();
					await payPromise(mpAppPay, {
						payParams: JSON.parse(__Data.data.payData) as PayParamMap[PayType.WX],
						isTrace,
						requireOrder
					});
					return
				}
				// #endif
				const userAgent = navigator.userAgent || navigator.vendor || window.opera || 'Unknown';
				if (/iPad|iPhone|iPod/.test(userAgent) && !window.MSStream) {
					top!.location.href = __Data.data.payData;
				} else {
					// 非ios则新开窗口
					window.open(__Data.data.payData);
				}
				// #endif
				// #ifdef MP
				// 拉半屏小程序支付
				wx.openEmbeddedMiniProgram({
					appId: __Data.appid,
					path: `pages/hub/miniLite?q=${encodeURIComponent(__Data.data.payData)}&amount=${payMoney}`
				});

				// #endif
				// #ifdef APP

				if (__Data.payType === 'CASHIER_ALIH5' || __Data.payType === 'CASHIER_WXH5') {
					uni.sendNativeEvent(
						'handleBrowserPay',
						__Data.data.payData,
						(ret) => { }
					);
					hasShowPayModal = true;
					showPayModalCB = () => {
						uni.hideLoading();
						getPayStatus();
					};
				} else {
					uni.sendNativeEvent(
						'handleWxAppletPay',
						{
							userName: __Data.originalId, //小程序的原始id，联系业务经理获取
							path: `pages/hub/lite?q=${encodeURIComponent(__Data.data.payData)}&amount=${payMoney}`, //需要跳转的页面及参数
							miniprogramType: 0 //这里是不同的环境（默认0）//0是正式环境  1测试版 2是体验版本
						},
						(ret) => { }
					);
				}

				// #endif

				hasShowPayModal = true;
				showPayModalCB = () => {
					uni.hideLoading();
					getPayStatus();
				};
			} else if (payType === PayType.FAST) {
				uni.hideLoading();
				const __Data : JinQianBaPayData = JSON.parse(payParams as string);
				console.log(__Data)

				// #ifdef APP-PLUS
				appOpenWebUrl(__Data.data.qrData)
				// #endif
				// #ifdef MP-WEIXIN
				uni.hideLoading();
				// await payPromise(mpAppPay, {
				// 	payParams: JSON.parse(__Data.data.qrData) as PayParamMap[PayType.WX],
				// 	isTrace,
				// 	requireOrder
				// });
				let jsApi = JSON.parse(__Data.data.jsApi)
				jsApi = {
					...jsApi,
					envVersion: jsApi.env_version,
					appId: jsApi.appid,
					path: `${jsApi.path}?${jsApi.query}`
				}
				uni.navigateToMiniProgram(jsApi)
				// #endif

				// #ifdef MP-ALIPAY
				await payPromise(alimappPay, {
					payParams: __Data.data.qrData as miniappPayParamMap[PayType.UIPAY]
				});
				// #endif
				// #ifdef SUBSCRIPTION || PRIVATE
				uni.hideLoading();
				await payPromise(mpAppPay, {
					payParams: __Data.data.qrData
				});
				return
				// #endif
				// #ifdef H5
				if ((payParams as miniappPayParamMap[PayType.CYBERSOURCE]) && (payParams as miniappPayParamMap[PayType.CYBERSOURCE])[0].bindCardId) {
					// 快捷支付
					uni.$emit('fastPayWithPayCode', resolveData.paycode)
				} else {
					openWebUrl(__Data.data.qrData)
				}
				// #endif
				setTimeout(() => {
					showPayModalCB = () => {
						uni.hideLoading();
						getPayStatus();
					};
				}, 1500)
			} else {

				payLoading.value = true;
				await payPromise(supperAppPay, payType, resolveData?.data);
				payLoading.value = false



			}

			//  else if (payType === PayType.STRIPE) {
			// 	// STRIPE支付
			// 	stripePay(resolveData.data as PayParamMap[PayType.STRIPE])

			// 	hasShowPayModal = true
			// 	showPayModalCB = () => {
			// 		uni.hideLoading()
			// 		getPayStatus()
			// 	}

			// } else if (payType === PayType.YABAND) {
			// 	// 雅本支付
			// 	yaBandPay(resolveData.data as PayParamMap[PayType.YABAND])
			// 	hasShowPayModal = true
			// 	showPayModalCB = () => {
			// 		uni.hideLoading()
			// 		getPayStatus()
			// 	}
			// } else if (payType === PayType.HM) {
			// 	// 河马支付
			// 	// #ifdef APP-PLUS
			// 	await payPromise(sandPay, {
			// 		payParams: resolveData.data as PayParamMap[PayType.HM]
			// 	})
			// 	return
			// 	// #endif
			// 	// #ifdef MP-WEIXIN || SUBSCRIPTION || PRIVATE
			// 	if (subPayType === 'h5') {
			// 		uni.hideLoading()
			// 		top!.location.href = payUrl
			// 	}  else {
			// 		await payPromise(mpAppPay, {
			// 			payParams: payParams as miniappPayParamMap[PayType.HM],
			// 			isTrace,
			// 			requireOrder
			// 		})
			// 	}
			// 	return
			// 	// #endif
			// 	//  #ifdef H5
			// 	uni.hideLoading()
			// 	top!.location.href = payUrl
			// 	// #endif
			// } else if (payType === PayType.SAND) {
			// 	// 杉德支付
			// 	// #ifdef APP-PLUS
			// 	await payPromise(sandPay, {
			// 		payParams: resolveData.data as PayParamMap[PayType.SAND]
			// 	})
			// 	// #endif

			// 	// #ifdef MP-WEIXIN || SUBSCRIPTION || PRIVATE
			// 	if (subPayType === 'h5') {
			// 		uni.hideLoading()
			// 		top!.location.href = payUrl
			// 	} else if (subPayType === 'h5_browser') {
			// 		// #ifdef SUBSCRIPTION
			// 		// 公众号支付宝支付，这里是婆罗的，saas的不做

			// 		// #endif
			// 	} else {
			// 		await payPromise(mpAppPay, {
			// 			payParams: payParams as miniappPayParamMap[PayType.SAND],
			// 			isTrace,
			// 			requireOrder
			// 		})
			// 	}
			// 	// #endif

			// 	//  #ifdef H5
			// 	uni.setStorageSync(storageKey, resolveData[orderIdKey])
			// 	uni.hideLoading()
			// 	top!.location.href = payUrl
			// 	return
			// 	// #endif

			// } else if (payType === PayType.UIPAY) {
			// 	// 支付宝小程序支付
			// 	// #ifdef MP-ALIPAY
			// 	uni.hideLoading()
			// 	await payPromise(alimappPay, {
			// 		payParams: payParams as miniappPayParamMap[PayType.UIPAY],
			// 	})
			// 	// #endif

			// } else if (payType === PayType.CYBERSOURCE) {
			// 	// #ifdef H5
			// 	uni.hideLoading()
			// 	uni.setStorageSync('cybersource', payParams as miniappPayParamMap[PayType.CYBERSOURCE])
			// 	uni.redirectTo({
			// 		url: `/pages/cybersource/index`
			// 	})
			// 	// #endif
			// } else {

			// 	// 走正常支付流程
			// 	// #ifdef HTML5
			// 	// 浏览器的支付，跳转至接口返回的地址
			// 	uni.setStorageSync(storageKey, resolveData[orderIdKey])
			// 	uni.hideLoading()
			// 	top!.location.href = payUrl
			// 	// #endif

			// 	// #ifdef MP-WEIXIN || SUBSCRIPTION || PRIVATE
			// 	// 小程序、公众号、私域下，除了默认钱包支付就是微信支付，此处走微信支付
			// 	uni.hideLoading()
			// 	await payPromise(mpAppPay, {
			// 		payParams: payParams as PayParamMap[PayType.WX],
			// 		isTrace,
			// 		requireOrder
			// 	})

			// 	// #endif

			// 	// #ifdef APP-PLUS
			// 	uni.hideLoading()
			// 	// includes判断导致ts无法推导出此处不含PayType.SYS，改用断言
			// 	await payPromise(appPay, {
			// 		payType: payType as (PayType.WX | PayType.ZFB),
			// 		payParams: payParams as (miniappPayParamMap[PayType.WX] | miniappPayParamMap[PayType.ZFB]),
			// 	})
			// 	// #endif

			// }
		}
		return true;
	};

	const getH5PayResult = <A extends CbRequestApi>(
		successUrl : string,
		storageKey : string,
		api : A,
		hasJump = false
	) : Promise<{
		res : PurchaseGoodsPayData;
		orderId : string;
	}> =>
		new Promise((resolve, reject) => {
			// #ifdef HTML5 || PREVIEW
			let orderId : string = uni.getStorageSync(storageKey);
			uni.removeStorageSync(storageKey);
			if (orderId) {
				ctx.$showModal({
					content: t('classify.是否支付成功'),
					success: (res) => {
						if (res.confirm) {
							payLoading.value = true;
							reRequest(api, 0, orderId)
								.then((resultRes) => {
									resolve({
										res: resultRes,
										orderId
									});
									if (hasJump) {
										ctx.$goRedirectTo(`/pages/${successUrl}?type=4&id=${resultRes.orderId}`);
									}
								})
								.catch(() => {
									reject();
								})
								.finally(() => {
									payLoading.value = false;
								});
						}
					}
				});
				return;
			}
			// #endif
			reject();
		});

	onShow(() => {
		if (hasShowPayModal) {
			ctx.$showModal({
				content: t('classify.是否支付成功'),
				success: (res) => {
					if (res.confirm) {
						showPayModalCB?.();
					}
				}
			});
		}
	});

	return {
		payLoading,
		systemPay,
		checkCardPay,
		cardValidCodePopupShow,
		handleCardPay,
		handleCancelCardPay,
		getH5PayResult
	};
};